package org.skipper.redission.spring.boot;

import com.google.common.base.Splitter;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.log4j.Log4j2;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.StringCodec;
import org.redisson.config.Config;
import org.redisson.spring.starter.RedissonAutoConfiguration;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * Description:
 *
 * @author shoujian
 * Date: 2020-12-21
 * Time: 9:52 下午
 */
@Configuration
@EnableConfigurationProperties({RedissonClientConf.class})
@AutoConfigureBefore(RedissonAutoConfiguration.class)
@Log4j2
public class SkipperRedissonAutoConfiguration implements ApplicationContextAware{

    private ApplicationContext applicationContext;

    private DefaultListableBeanFactory defaultListableBeanFactory;

    private List<String> singleRedisSourceNames = new ArrayList<>();

    private List<String> clusterRedisSourceNames = new ArrayList<>();

    @Bean
    public BeanPostProcessor redisBeanPostProcessor(RedissonClientConf properties) throws IOException {
        registerRedissonClient(properties);
        return new BeanPostProcessor() {
            @Override
            public Object postProcessAfterInitialization(Object arg0,
                                                         String arg1) throws BeansException {
                return arg0;
            }

            @Override
            public Object postProcessBeforeInitialization(Object arg0,
                                                          String arg1) throws BeansException {
                return arg0;
            }

        };
    }

    private void registerRedissonClient(RedissonClientConf properties) throws IOException {
        log.info("----registerRedissonClient----");
        if (properties != null) {
            SkipperSingleServerConfig[] skipperSingleServerConfigs = properties.getSkipperSingleServerConfigs();

            if (!CollectionUtils.isEmpty(singleRedisSourceNames) && skipperSingleServerConfigs != null && skipperSingleServerConfigs.length > 0) {
                for (SkipperSingleServerConfig skipperSingleServerConfig : skipperSingleServerConfigs) {
                    if (singleRedisSourceNames.contains(skipperSingleServerConfig.getSourceName())) {
                        Config config = Config.fromYAML(skipperSingleServerConfig.getConfig().toYAML());
                        config.setCodec(StringCodec.INSTANCE);
                        RedissonClient redissonClient = Redisson.create(config);

                        defaultListableBeanFactory.registerSingleton(skipperSingleServerConfig.getSourceName(), redissonClient);
                    }
                }
            }

            SkipperClusterServerConfig[] skipperClusterServerConfigs = properties.getSkipperClusterServerConfigs();

            if (!CollectionUtils.isEmpty(clusterRedisSourceNames) && skipperClusterServerConfigs != null && skipperClusterServerConfigs.length > 0) {
                for (SkipperClusterServerConfig skipperClusterServerConfig : skipperClusterServerConfigs) {
                    if (clusterRedisSourceNames.contains(skipperClusterServerConfig.getSourceName())) {
                        Config config = Config.fromYAML(skipperClusterServerConfig.getConfig().toYAML());
                        config.setCodec(StringCodec.INSTANCE);
                        RedissonClient redissonClient = Redisson.create(config);

                        defaultListableBeanFactory.registerSingleton(skipperClusterServerConfig.getSourceName(), redissonClient);
                    }
                }
            }

        }

    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        setRedisSourceNames(applicationContext);
        // 获取BeanFactory
        this.defaultListableBeanFactory = (DefaultListableBeanFactory) this.applicationContext
                .getAutowireCapableBeanFactory();
    }

    private void setRedisSourceNames(ApplicationContext applicationContext) {
        String singleSourceNames = applicationContext.getEnvironment().getProperty("redisson.singleRedis.source.names");
        String clusterSourceNames = applicationContext.getEnvironment().getProperty("redisson.HAClusterRedis.source.names");

        if (StringUtils.isNotEmpty(singleSourceNames)) {
            singleRedisSourceNames.addAll(Splitter.on(",").trimResults().splitToList(singleSourceNames));
        }

        if (StringUtils.isNotEmpty(clusterSourceNames)) {
            clusterRedisSourceNames.addAll(Splitter.on(",").trimResults().splitToList(clusterSourceNames));
        }

    }

}
